#include "4.h"

void init_page1(GtkWidget *note) //notebook第一页系统信息显示初始化
{
    GtkWidget *vbox;
    GtkWidget *label, *frame_system_kernel, *frame_cpu, *frame_runtime, *frame_about;
    FILE *fp;
    int i = 0;
    char *title[] = {"主机名", "系统类型", "内核版本", "内核编译日期"};
    char *filename[] = {HOSTNAME, OSTYPE, OSRELEASE, VERSION};
    char buf[BUFFERSIZE], temp[BUFFERSIZE];
    vbox = gtk_vbox_new(FALSE, 10);
    label = gtk_label_new("系 统 信 息");
    gtk_notebook_append_page(GTK_NOTEBOOK(note), vbox, label);
    frame_system_kernel = gtk_frame_new("系统和内核");
    frame_cpu = gtk_frame_new("CPU信息");
    frame_runtime = gtk_frame_new("时间信息");
    frame_about = gtk_frame_new("关于");
    gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);

    gtk_box_pack_start(GTK_BOX(vbox), frame_system_kernel, TRUE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), frame_cpu, TRUE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), frame_runtime, TRUE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), frame_about, TRUE, FALSE, 0);

    vbox = gtk_vbox_new(FALSE, 0); //系统和内核信息纵向组件盒
    gtk_container_add(GTK_CONTAINER(frame_system_kernel), vbox);
    for (; i < 4; i++) //显示系统和内核信息
    {
        if ((fp = fopen(filename[i], "r")) == NULL)
            gtk_main_quit();
        fgets(buf, BUFFERSIZE, fp);
        if (i == 3)
            strcpy(buf, strstr(buf, "SMP") + 4);
        buf[strlen(buf) - 1] = '\0';
        sprintf(temp, "%s : %s", title[i], buf);
        label = gtk_label_new(temp);
        gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); //标签左对齐
        gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 0);
        fclose(fp);
    }

    vbox = gtk_vbox_new(FALSE, 0); //cpu纵向组件盒
    gtk_container_add(GTK_CONTAINER(frame_cpu), vbox);
    if ((fp = fopen(CPUVERSION, "r")) == NULL)
        gtk_main_quit();
    fgets(buf, BUFFERSIZE, fp);
    fgets(buf, BUFFERSIZE, fp);
    sscanf(buf, "%*[^:]: %s", temp);
    sprintf(buf, "类型 : %s", temp);
    label = gtk_label_new(buf);
    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); //标签左对齐
    gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 0);
    fgets(buf, BUFFERSIZE, fp);
    fgets(buf, BUFFERSIZE, fp);
    fgets(buf, BUFFERSIZE, fp);
    sscanf(buf, "%*[^:]: %[^\n]", temp);
    sprintf(buf, "名称 : %s", temp);
    label = gtk_label_new(buf);
    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); //标签左对齐
    gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 0);
    fgets(buf, BUFFERSIZE, fp);
    fgets(buf, BUFFERSIZE, fp);
    fgets(buf, BUFFERSIZE, fp);
    sscanf(buf, "%*[^:]: %s", temp);
    sprintf(buf, "频率 : %s MHz", temp);
    label = gtk_label_new(buf);
    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); //标签左对齐
    gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 0);
    fgets(buf, BUFFERSIZE, fp);
    sscanf(buf, "%*[^:]: %[^\n]", temp);
    sprintf(buf, "Cache : %s", temp);
    label = gtk_label_new(buf);
    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); //标签左对齐
    gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 0);
    fclose(fp);

    vbox = gtk_vbox_new(FALSE, 0); //时间信息纵向组件盒
    gtk_container_add(GTK_CONTAINER(frame_runtime), vbox);
    if ((fp = fopen(UPTIME, "r")) == NULL)
        gtk_main_quit();
    fgets(buf, BUFFERSIZE, fp);
    fclose(fp);
    long r_time;
    sscanf(buf, "%ld", &r_time);
    get_start_time(r_time, temp); //获取系统启动时间
    sprintf(buf, "系统启动时间 : %s", temp);
    label = gtk_label_new(buf);
    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); //标签左对齐
    gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 0);
    sprintf(buf, "系统持续运行时间 : %ld.00秒", r_time);
    run_time_label = gtk_label_new(buf);
    gtk_misc_set_alignment(GTK_MISC(run_time_label), 0.0, 0.0); //标签左对齐
    gtk_box_pack_start(GTK_BOX(vbox), run_time_label, TRUE, FALSE, 0);
    timeout_tag[0] = gtk_timeout_add(1000, refrush_run_time, NULL);

    vbox = gtk_vbox_new(FALSE, 0); //about纵向组件盒
    gtk_container_add(GTK_CONTAINER(frame_about), vbox);
    label = gtk_label_new("v 1.0");
    gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 0);
    label = gtk_label_new("Copyright © 2020 Zhenyang Chen");
    gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 0);
}

void init_page2(GtkWidget *note) //notebook第二页进程信息初始化
{
    GtkWidget *scrolled_window;
    GtkWidget *label;
    GtkWidget *vbox;

    const char *title[] = {"进程名", "PID", "PPID", "状态", "内存", "优先级"};
    const int width[] = {240, 45, 45, 35, 60, 45};
    vbox = gtk_vbox_new(FALSE, 0);
    label = gtk_label_new("进 程 信 息");
    gtk_notebook_append_page(GTK_NOTEBOOK(note), vbox, label);
    gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);

    scrolled_window = gtk_scrolled_window_new(NULL, NULL);               //滚动窗口
    gtk_widget_set_size_request(scrolled_window, 300, 400);              //设置滚动窗口大小
    gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, FALSE, FALSE, 0); //滚动窗口放入纵向组件盒

    GtkWidget *clist = gtk_clist_new(6);
    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), clist); //将列表放入滚动窗口

    for (int i = 0; i < 6; i++) //设置标题名、宽度并使标题居中对齐
    {
        gtk_clist_set_column_title(GTK_CLIST(clist), i, title[i]);
        gtk_clist_set_column_justification(GTK_CLIST(clist), i, GTK_JUSTIFY_CENTER);
        gtk_clist_set_column_width(GTK_CLIST(clist), i, width[i]);
    }
    gtk_clist_column_titles_show(GTK_CLIST(clist));

    get_process_info(clist); //获取进程信息

    GtkWidget *table = gtk_table_new(5, 6, FALSE);
    gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, FALSE, 10);

    label = gtk_label_new("请输入想要结束的进程");
    gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
    GtkWidget *comboBox = gtk_combo_box_new_text();
    gtk_combo_box_append_text(GTK_COMBO_BOX(comboBox), "名称");
    gtk_combo_box_append_text(GTK_COMBO_BOX(comboBox), "PID");
    gtk_combo_box_set_active(GTK_COMBO_BOX(comboBox), -1);
    gtk_signal_connect(GTK_OBJECT(comboBox), "changed", GTK_SIGNAL_FUNC(set_pid_name_flag), NULL);
    GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), comboBox, FALSE, FALSE, 0);
    gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 1, 2, 0, 0, 0, 0);

    // label = gtk_label_new("  请输入想要结束的进程名：");
    // gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, 0, 0, 0, 0);
    GtkWidget *process_entry = gtk_entry_new();
    gtk_table_attach(GTK_TABLE(table), process_entry, 1, 2, 1, 2, 0, 0, 0, 0);
    gtk_entry_set_max_length(GTK_ENTRY(process_entry), 100);
    gtk_entry_set_text(GTK_ENTRY(process_entry), "");

    GtkWidget *button = gtk_button_new_with_label("结束进程");
    gtk_table_attach(GTK_TABLE(table), button, 2, 3, 1, 2, GTK_EXPAND, 0, 0, 0);
    gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); //未选中行时，结束进程按钮不使能
    //绑定文本输入改动信号，设置按钮使能
    gtk_signal_connect(GTK_OBJECT(process_entry), "changed", GTK_SIGNAL_FUNC(changed_callback), button);
    //绑定行选择，再点击结束进程按钮即可结束所选进程
    // gtk_signal_connect(GTK_OBJECT(clist), "select_row", GTK_SIGNAL_FUNC(select_row_callback), button);
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(kill_process), clist);

    label = gtk_label_new("  请输入想要启动的进程名：");
    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0);
    process_entry = gtk_entry_new();
    gtk_table_attach(GTK_TABLE(table), process_entry, 1, 2, 3, 4, 0, 0, 0, 0);
    gtk_entry_set_max_length(GTK_ENTRY(process_entry), 100);
    gtk_entry_set_text(GTK_ENTRY(process_entry), "");
    button = gtk_button_new_with_label("启动进程");
    gtk_table_attach(GTK_TABLE(table), button, 2, 3, 3, 4, GTK_EXPAND, 0, 0, 0);
    gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); //未输入进程名时，启动束进程按钮不使能
    //绑定文本输入改动信号，设置按钮使能
    gtk_signal_connect(GTK_OBJECT(process_entry), "changed", GTK_SIGNAL_FUNC(changed_callback1), button);
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(run_process), button);

    // label = gtk_label_new("");
    // gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 5, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
    // button = gtk_button_new_with_label("刷  新");
    // gtk_table_attach(GTK_TABLE(table), button, 4, 5, 0, 5, 0, 0, 0, 0);
    // g_signal_connect(G_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(refrush_process), clist);
    // label = gtk_label_new("");
    // gtk_table_attach(GTK_TABLE(table), label, 5, 6, 0, 5, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);

    timeout_tag[1] = gtk_timeout_add(1000, refrush_process, clist);

    char content[BUFFERSIZE];
    GtkWidget *frame = gtk_frame_new("进程信息");
    hbox = gtk_hbox_new(FALSE, 0);

    gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
    gtk_container_add(GTK_CONTAINER(frame), hbox);

    GtkWidget *vbox1 = gtk_vbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0);
    sprintf(content, "All : %d", a);
    label1 = gtk_label_new(content);

    gtk_box_pack_start(GTK_BOX(vbox1), label1, TRUE, TRUE, 0);
    sprintf(content, "Runable : %d", r);
    label2 = gtk_label_new(content);
    gtk_box_pack_start(GTK_BOX(vbox1), label2, TRUE, TRUE, 0);

    vbox1 = gtk_vbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0);
    sprintf(content, "Idle : %d", idle);
    label3 = gtk_label_new(content);
    gtk_box_pack_start(GTK_BOX(vbox1), label3, TRUE, TRUE, 0);
    sprintf(content, "Sleeping : %d", s);
    label4 = gtk_label_new(content);
    gtk_box_pack_start(GTK_BOX(vbox1), label4, TRUE, TRUE, 0);

    vbox1 = gtk_vbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0);
    sprintf(content, "Zombie : %d", z);
    label5 = gtk_label_new(content);
    gtk_box_pack_start(GTK_BOX(vbox1), label5, TRUE, TRUE, 0);
    sprintf(content, "Traced : %d", t);
    label6 = gtk_label_new(content);
    gtk_box_pack_start(GTK_BOX(vbox1), label6, TRUE, TRUE, 0);
}

void init_page3(GtkWidget *note) //notebook第三页cpu、mem图形化显示初始化
{
    GtkWidget *label;
    GtkWidget *vbox;
    GtkWidget *cpu_frame, *mem_frame;
    GtkWidget *table, *hrule, *vrule;
    GtkWidget *draw_area;

    label = gtk_label_new("CPU / MEM");
    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
    gtk_notebook_insert_page(GTK_NOTEBOOK(note), vbox, label, 2); //将图形显示加入到尾页

    cpu_frame = gtk_frame_new("CPU历史");
    gtk_box_pack_start(GTK_BOX(vbox), cpu_frame, FALSE, FALSE, 0);
    table = gtk_table_new(2, 2, FALSE);
    gtk_container_add(GTK_CONTAINER(cpu_frame), table);

    cpu_draw = gtk_drawing_area_new();
    gtk_drawing_area_size(GTK_DRAWING_AREA(cpu_draw), 600, 200);
    gtk_table_attach(GTK_TABLE(table), cpu_draw, 1, 2, 1, 2, GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
    gtk_widget_set_events(cpu_draw, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
    // gtk_widget_modify_bg(GTK_WIDGET(cpu_draw), GTK_STATE_NORMAL, &color1); //设置背景为黑色
    gtk_signal_connect(GTK_OBJECT(cpu_draw), "expose_event", (GtkSignalFunc)expose_event, NULL);
    gtk_signal_connect(GTK_OBJECT(cpu_draw), "configure_event", (GtkSignalFunc)configure_event, NULL);

    hrule = gtk_hruler_new();
    gtk_ruler_set_metric(GTK_RULER(hrule), GTK_PIXELS);
    gtk_ruler_set_range(GTK_RULER(hrule), 120, 0, 120, 600);
    gtk_table_attach(GTK_TABLE(table), hrule, 1, 2, 0, 1, GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
    g_signal_connect_swapped(G_OBJECT(cpu_draw), "motion_notify_event", G_CALLBACK(EVENT_METHOD(hrule, motion_notify_event)), hrule);

    vrule = gtk_vruler_new();
    gtk_ruler_set_metric(GTK_RULER(vrule), GTK_PIXELS);
    gtk_ruler_set_range(GTK_RULER(vrule), 100, 0, 100, 200);
    gtk_table_attach(GTK_TABLE(table), vrule, 0, 1, 1, 2, GTK_SHRINK, GTK_FILL, 0, 0);
    g_signal_connect_swapped(G_OBJECT(cpu_draw), "motion_notify_event", G_CALLBACK(EVENT_METHOD(vrule, motion_notify_event)), vrule);

    mem_frame = gtk_frame_new("内存历史");
    gtk_box_pack_start(GTK_BOX(vbox), mem_frame, FALSE, FALSE, 0);
    table = gtk_table_new(2, 2, FALSE);
    gtk_container_add(GTK_CONTAINER(mem_frame), table);

    mem_draw = gtk_drawing_area_new();
    gtk_drawing_area_size(GTK_DRAWING_AREA(mem_draw), 600, 200);
    gtk_table_attach(GTK_TABLE(table), mem_draw, 1, 2, 1, 2, GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
    gtk_widget_set_events(mem_draw, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);

    hrule = gtk_hruler_new();
    gtk_ruler_set_metric(GTK_RULER(hrule), GTK_PIXELS);
    gtk_ruler_set_range(GTK_RULER(hrule), 120, 0, 120, 600);
    gtk_table_attach(GTK_TABLE(table), hrule, 1, 2, 0, 1, GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
    g_signal_connect_swapped(G_OBJECT(mem_draw), "motion_notify_event", G_CALLBACK(EVENT_METHOD(hrule, motion_notify_event)), hrule);

    vrule = gtk_vruler_new();
    gtk_ruler_set_metric(GTK_RULER(vrule), GTK_PIXELS);
    gtk_ruler_set_range(GTK_RULER(vrule), 100, 0, 100, 200);
    gtk_table_attach(GTK_TABLE(table), vrule, 0, 1, 1, 2, GTK_SHRINK, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
    g_signal_connect_swapped(G_OBJECT(mem_draw), "motion_notify_event", G_CALLBACK(EVENT_METHOD(vrule, motion_notify_event)), vrule);

    //CPU图例
    table = gtk_table_new(10, 1, FALSE);
    gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
    label = gtk_label_new(" ");
    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
    label = gtk_label_new("CPU :");
    gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1, 0, 0, 0, 0);
    draw_area = gtk_drawing_area_new();
    gtk_drawing_area_size(GTK_DRAWING_AREA(draw_area), 100, 40);
    gtk_signal_connect(GTK_OBJECT(draw_area), "expose_event", (GtkSignalFunc)expose_event1, NULL);
    gtk_table_attach(GTK_TABLE(table), draw_area, 2, 3, 0, 1, 0, 0, 0, 0);

    //内存图例
    label = gtk_label_new("MEM :");
    gtk_table_attach(GTK_TABLE(table), label, 4, 5, 0, 1, 0, 0, 0, 0);
    draw_area = gtk_drawing_area_new();
    gtk_drawing_area_size(GTK_DRAWING_AREA(draw_area), 100, 40);
    gtk_signal_connect(GTK_OBJECT(draw_area), "expose_event", (GtkSignalFunc)expose_event3, NULL);
    gtk_table_attach(GTK_TABLE(table), draw_area, 5, 6, 0, 1, 0, 0, 0, 0);

    //swap图例
    label = gtk_label_new("swap :");
    gtk_table_attach(GTK_TABLE(table), label, 7, 8, 0, 1, 0, 0, 0, 0);
    draw_area = gtk_drawing_area_new();
    gtk_drawing_area_size(GTK_DRAWING_AREA(draw_area), 100, 40);
    gtk_signal_connect(GTK_OBJECT(draw_area), "expose_event", (GtkSignalFunc)expose_event2, NULL);
    gtk_table_attach(GTK_TABLE(table), draw_area, 8, 9, 0, 1, 0, 0, 0, 0);
    label = gtk_label_new(" ");
    gtk_table_attach(GTK_TABLE(table), label, 9, 10, 0, 1, GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);

    timeout_tag[2] = gtk_timeout_add(1000, refrush_draw_cpu_mem_activity, NULL);
}

void init_color_front() //初始化color和gc_front
{
    color1.red = color1.blue = color1.green = 0;        //黑色
    color2.red = color2.blue = color2.green = 20000;    //白色
    color3.red = color3.blue = 0, color3.green = 65535; //绿色

    gc_front1 = gdk_gc_new(GDK_DRAWABLE(cpu_draw->window));
    gdk_gc_set_rgb_fg_color(gc_front1, &color2);

    gc_front2 = gdk_gc_new(cpu_draw->window);
    gdk_gc_set_rgb_fg_color(gc_front2, &color3);
}

gint refrush_draw_cpu_mem_activity() //更新cpu和内存活动图
{

    int i = y_co.i;
    double xstep = 1.0 * cpu_draw->allocation.width / 120; //x方向步长
    double x0 = 0, x = xstep;
    int cpu_y0 = y_co.cy[i], cpu_y = y_co.cy[(i + 1) % 121];
    int mem_y0 = y_co.my[i], mem_y = y_co.my[(i + 1) % 121];
    int swap_y0 = y_co.sy[i], swap_y = y_co.sy[(i + 1) % 121];

    //清除原绘图
    // GdkPixbuf *buf = gdk_pixbuf_get_from_drawable(NULL, cpu_map, gdk_drawable_get_colormap(cpu_map), 0, 0, 0, 0, -1, -1);
    gdk_draw_rectangle(cpu_draw->window, cpu_draw->style->white_gc, TRUE, 0, 0, cpu_draw->allocation.width, cpu_draw->allocation.height);
    gdk_draw_rectangle(mem_draw->window, mem_draw->style->white_gc, TRUE, 0, 0, mem_draw->allocation.width, mem_draw->allocation.height);
    // gdk_draw_rectangle(cpu_map, cpu_draw->style->black_gc, TRUE, 0, 0, cpu_draw->allocation.width, cpu_draw->allocation.height);
    draw_init();
    // gdk_pixbuf_unref(buf);
    for (int j = 0; j < 120; j++)
    {
        gdk_draw_line(cpu_draw->window, gc_front2, x0, cpu_y0, x, cpu_y);
        gdk_draw_line(mem_draw->window, gc_front4, x0, mem_y0, x, mem_y);
        gdk_draw_line(mem_draw->window, gc_front3, x0, swap_y0, x, swap_y);
        // printf("%d %d\n", cpu_y0, mem_y0);
        i = (i + 1) % 121;
        x0 = x, x += xstep;
        cpu_y0 = cpu_y, cpu_y = y_co.cy[i];
        mem_y0 = mem_y, mem_y = y_co.my[i];
        swap_y0 = swap_y, swap_y = y_co.sy[i];
    }
}

bool draw_init()
{
    // printf("begin init\n");
    // cpu_draw = GTK_WIDGET(cpu_draw);
    // init_color_front();
    int xstep = cpu_draw->allocation.width / 6, ystep = cpu_draw->allocation.height / 5;
    int hx1 = 0, hy1 = ystep, hx2 = cpu_draw->allocation.width, hy2 = ystep;  //横向划线两端点坐标
    int vx1 = xstep, vy1 = 0, vx2 = xstep, vy2 = cpu_draw->allocation.height; //纵向划线两端点坐标

    for (int i = 0; i < 4; i++)
    {
        gdk_draw_line(cpu_draw->window, gc_front1, hx1, hy1, hx2, hy2);
        gdk_draw_line(mem_draw->window, gc_front1, hx1, hy1, hx2, hy2);
        // gdk_draw_line(cpu_map, gc_front1, hx1, hy1, hx2, hy2);
        hy1 += ystep;
        hy2 = hy1;
    }
    for (int i = 0; i < 6; i++)
    {
        gdk_draw_line(cpu_draw->window, gc_front1, vx1, vy1, vx2, vy2);
        gdk_draw_line(mem_draw->window, gc_front1, vx1, vy1, vx2, vy2);
        // gdk_draw_line(cpu_map, gc_front1, vx1, vy1, vx2, vy2);
        vx1 += xstep;
        vx2 = vx1;
    }
    // printf("ends init\n");
    return TRUE;
}

//暴露事件回调函数
gint expose_event(GtkWidget *widget, GdkEventExpose *event)
{
    refrush_draw_cpu_mem_activity();
    // printf("expose\n");
    return FALSE;
}

//暴露事件回调函数--CPU图例
gint expose_event1(GtkWidget *widget, GdkEventExpose *event)
{
    gdk_draw_line(widget->window, gc_front2, 10, 20, 80, 20);
    return FALSE;
}

//暴露事件回调函数--内存图例
gint expose_event2(GtkWidget *widget, GdkEventExpose *event)
{
    gdk_draw_line(widget->window, gc_front3, 10, 20, 80, 20);
    return FALSE;
}

//暴露事件回调函数--swap图例
gint expose_event3(GtkWidget *widget, GdkEventExpose *event)
{
    gdk_draw_line(widget->window, gc_front4, 10, 20, 80, 20);
    return FALSE;
}

int configure_event(GtkWidget *widget, GdkEventConfigure *event)
{
    color1.red = color1.blue = color1.green = 0;            //黑色
    color2.red = color2.blue = color2.green = 58000;        //白色
    color3.red = color3.blue = 0, color3.green = 50000;     //绿色
    color4.red = 20000, color4.blue = color4.green = 60000; //青色
    color5.red = 65535, color5.blue = color5.green = 0;     //红色

    gc_front1 = gdk_gc_new(GDK_DRAWABLE(widget->window));
    gdk_gc_set_rgb_fg_color(gc_front1, &color2);
    gc_front2 = gdk_gc_new(widget->window);
    gdk_gc_set_rgb_fg_color(gc_front2, &color3);
    gc_front3 = gdk_gc_new(widget->window);
    gdk_gc_set_rgb_fg_color(gc_front3, &color4);
    gc_front4 = gdk_gc_new(widget->window);
    gdk_gc_set_rgb_fg_color(gc_front4, &color5);
    // printf("configure\n");
    return TRUE;
}

//获取系统启动时间
void get_start_time(long r_time, char *temp)
{
    time_t timep;
    struct tm *p;
    time(&timep);
    timep -= r_time;
    p = localtime(&timep);
    memset(temp, '\0', BUFFERSIZE);
    strftime(temp, BUFFERSIZE, "%Y-%m-%d %H:%M:%S", p);
}

//获取cpu使用率
void get_cpu_rate(char *temp_buf)
{
    FILE *fp;
    char buf[BUFFERSIZE];
    if ((fp = fopen(STAT, "r")) == NULL)
    {
        perror("Open SATA error");
        gtk_main_quit();
    }
    fgets(buf, BUFFERSIZE, fp);
    fclose(fp);
    unsigned total1;
    unsigned user, nice, sys, idl1, iowait, irq, soft, steal, guest, g_nice;
    sscanf(buf, "%*s%u%u%u%u%u%u%u%u%u%u", &user, &nice, &sys, &idl1, &iowait, &irq,
           &soft, &steal, &guest, &g_nice);
    total1 = user + nice + sys + idl1 + iowait + irq + soft + steal + guest;
    usleep(200000);
    if ((fp = fopen(STAT, "r")) == NULL)
    {
        perror("Open SATA error");
        gtk_main_quit();
    }
    fgets(buf, BUFFERSIZE, fp);
    fclose(fp);
    unsigned total2, idl2, used, total;
    double ans;
    sscanf(buf, "%*s%u%u%u%u%u%u%u%u%u%u", &user, &nice, &sys, &idl2, &iowait, &irq,
           &soft, &steal, &guest, &g_nice);
    total2 = user + nice + sys + idl2 + iowait + irq + soft + steal + guest;
    total = total2 - total1;
    used = total - (idl2 - idl1);
    ans = 100.0 * used / total;
    y_co.cy[y_co.i] = (99.9 - ans) * 2;
    sprintf(temp_buf, "%%CPU : %.2lf", ans);
}

//获取mem使用率
void get_mem_rate(char *temp_buf)
{
    FILE *fp;
    char buf[BUFFERSIZE];
    unsigned total, avail, swap_total, swap_free;
    if ((fp = fopen(MEMINFO, "r")) == NULL)
    {
        perror("Open meminfo error");
        gtk_main_quit();
    }
    fgets(buf, BUFFERSIZE, fp);
    sscanf(buf, "%*s%u", &total);
    fgets(buf, BUFFERSIZE, fp);
    fgets(buf, BUFFERSIZE, fp);
    sscanf(buf, "%*s%u", &avail);
    for (int i = 0; i < 12; i++)
        fgets(buf, BUFFERSIZE, fp);
    sscanf(buf, "%*s%u", &swap_total);
    fgets(buf, BUFFERSIZE, fp);
    sscanf(buf, "%*s%u", &swap_free);
    fclose(fp);
    double ans = 100.0 * (total - avail) / total;
    y_co.my[y_co.i] = (100.0 - ans) * 2;
    y_co.sy[y_co.i] = 200.0 * swap_free / swap_total;
    y_co.i = (y_co.i + 1) % 121;
    sprintf(temp_buf, "%%MEM : %.2lf", ans);
}

//更新时间、CPU和内存占用率
gint refrush_time_CPU_mem()
{
    char temp_buf[BUFFERSIZE];
    //获取CPU使用率
    get_cpu_rate(temp_buf);
    gtk_label_set_text(GTK_LABEL(cpu_label), temp_buf);
    //获取mem使用率
    get_mem_rate(temp_buf);
    gtk_label_set_text(GTK_LABEL(mem_label), temp_buf);
    //获取时间
    get_start_time(0, temp_buf);
    gtk_label_set_text(GTK_LABEL(time_label), temp_buf);
    return TRUE;
}

//更新系统持续运行时间
gint refrush_run_time()
{
    FILE *fp;
    double r_time;
    char temp[BUFFERSIZE];
    if ((fp = fopen(UPTIME, "r")) == NULL)
    {
        perror("Open /proc/uptime error");
        gtk_main_quit();
    }
    fgets(temp, BUFFERSIZE, fp);
    sscanf(temp, "%lf", &r_time);
    sprintf(temp, "系统持续运行时间 : %.2lf秒", r_time);
    gtk_label_set_text(GTK_LABEL(run_time_label), temp);
    return TRUE;
}

//获取进程有关信息
void get_process_info(gpointer clist)
{
    // printf("before clean\n");
    gtk_clist_clear(GTK_CLIST(clist));
    gtk_clist_freeze(GTK_CLIST(clist));
    DIR *pdir = NULL;
    struct dirent *p_dirent;
    char temp_stat_path[64];
    char temp_statm_path[64];
    char content[BUFFERSIZE];
    FILE *fp = NULL;
    a = r = z = s = t = idle = 0;
    gchar *process_content[5];
    for (int i = 0; i < 6; i++) //初始化进程信息空间
        process_content[i] = (gchar *)malloc(128 * sizeof(gchar));
    pdir = opendir("/proc");
    if (!pdir)
    {
        perror("Open /proc file error");
        gtk_main_quit();
    }
    while (p_dirent = readdir(pdir)) //遍历进程文件夹，获取进程信息
    {
        if (p_dirent->d_name[0] >= '0' && p_dirent->d_name[0] <= '9') //判断是否是进程文件
        {
            sprintf(temp_stat_path, "/proc/%s/stat", p_dirent->d_name);
            sprintf(temp_statm_path, "/proc/%s/statm", p_dirent->d_name);
            fp = fopen(temp_stat_path, "r");
            if (fp)
            {
                fgets(content, BUFFERSIZE, fp);
                fclose(fp);
                sscanf(content, "%s (%s%s%s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%s",
                       process_content[1], process_content[0], process_content[3], process_content[2], process_content[5]);
                process_content[0][strlen(process_content[0]) - 1] = '\0';
            }
            else
                continue;

            fp = fopen(temp_statm_path, "r");
            if (fp)
            {
                fgets(content, BUFFERSIZE, fp);
                fclose(fp);
                sscanf(content, "%s", process_content[4]);
            }
            else
                continue;
            gtk_clist_append(GTK_CLIST(clist), process_content);
            a++;
            switch (process_content[3][0])
            {
            case 'S':
                (s)++;
                break;
            case 'R':
                (r)++;
                break;
            case 'Z':
                (z)++;
                break;
            case 'I':
                (idle)++;
                break;
            case 'T':
                (t)++;
                break;
            default:
                break;
            }
        }
    }
    gtk_clist_thaw(GTK_CLIST(clist));
    closedir(pdir);
    for (int i = 0; i < 6; i++) //释放进程信息空间
        free(process_content[i]);
}

void refrush_process_num()
{
    char content[64];
    sprintf(content, "All : %d", a);
    gtk_label_set_text(GTK_LABEL(label1), content);
    sprintf(content, "Runable : %d", r);
    gtk_label_set_text(GTK_LABEL(label2), content);
    sprintf(content, "Idle : %d", idle);
    gtk_label_set_text(GTK_LABEL(label3), content);
    sprintf(content, "Sleeping : %d", s);
    gtk_label_set_text(GTK_LABEL(label4), content);
    sprintf(content, "Zombie : %d", z);
    gtk_label_set_text(GTK_LABEL(label5), content);
    sprintf(content, "Traced : %d", t);
    gtk_label_set_text(GTK_LABEL(label6), content);
}

void set_pid_name_flag(GtkWidget *combo, gpointer data) //下拉框回调函数，设置从输入框接收的文本类型
{
    gchar *res = gtk_combo_box_get_active_text(GTK_COMBO_BOX(combo));
    if (strcmp(res, "PID") == 0)
    {
        proc_data.p_flag = TRUE;
    }
    else
    {
        proc_data.p_flag = FALSE;
    }
}

void changed_callback(GtkWidget *entry, gpointer button) //结束进程输入框输入变动回调函数
{
    gtk_widget_set_sensitive(GTK_WIDGET(button), TRUE); //有文本输入，按钮使能
    const gchar *entry_text;
    entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
    strcpy(proc_data.name, entry_text);
    // proc_data.n_flag = TRUE;
    // proc_data.flag = FALSE;
}

void changed_callback1(GtkWidget *entry, gpointer button) //启动进程输入框输入变动回调函数
{
    gtk_widget_set_sensitive(GTK_WIDGET(button), TRUE); //有文本输入，按钮使能
    const gchar *entry_text;
    entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
    strcpy(run_data.name, "./");
    strcat(run_data.name, entry_text);
    // printf("%s\n", run_data.name);
    run_data.n_flag = TRUE;
}

// //select_row的回调信号
// void select_row_callback(GtkWidget *clist1, gint row, gint column, GdkEventButton *event, gpointer data)
// {
//     gtk_widget_set_sensitive(GTK_WIDGET(data), TRUE); //行选中，按钮使能
//     gchar *text = NULL;
//     gtk_clist_get_text(GTK_CLIST(clist1), row, 1, &text);
//     sscanf(text, "%d", &proc_data.pid);
//     proc_data.row = row;
//     proc_data.n_flag = FALSE;
//     proc_data.flag = TRUE;
//     printf("%d %d\n", proc_data.pid, row);
// }

gint run_process(gpointer button) //点击按钮启动新进程响应函数
{
    if (run_data.n_flag)
    {
        if (access(run_data.name, X_OK) == -1) //文件不可执行
        {
            GtkWidget *dialog;
            dialog = gtk_message_dialog_new(GTK_WINDOW(window),
                                            GTK_DIALOG_DESTROY_WITH_PARENT,
                                            GTK_MESSAGE_ERROR,
                                            GTK_BUTTONS_OK,
                                            "文件不存在或不可执行，无法启动该进程！");
            gtk_window_set_title(GTK_WINDOW(dialog), "错误");
            gtk_widget_show(dialog);
            gtk_dialog_run(GTK_DIALOG(dialog));
            gtk_widget_destroy(dialog);
        }
        else
        {
            pid_t pid = fork();
            if (pid == 0)
            {
                char *execv_str[] = {NULL};
                if (execv(run_data.name, execv_str) < 0)
                {
                    perror("Execv error");
                    exit(-1);
                }
            }
        }
        // run_data.n_flag = FALSE;
    }
    return TRUE;
}

gint kill_process(GtkWidget *button, gpointer clist)
{
    // if (proc_data.flag) //通过行选择选定一个进程
    // {
    //     kill(proc_data.pid, SIGKILL);
    //     gtk_clist_remove(GTK_CLIST(clist), proc_data.row);
    //     proc_data.flag = FALSE;
    // }
    // if (proc_data.n_flag) //通过输入一个进程名/PID确定一个进程
    // {
    if (proc_data.p_flag == 0) //通过输入一个进程名确定一个进程
    {
        DIR *pdir = NULL;
        struct dirent *p_dirent;
        char con[BUFFERSIZE], temp_name[BUFFERSIZE];
        char temp_file_path[BUFFERSIZE];
        FILE *fp;
        pdir = opendir("/proc");
        if (!pdir)
        {
            perror("Open /proc file error");
            return FALSE;
        }
        while (p_dirent = readdir(pdir))
        {
            if (p_dirent->d_name[0] >= '0' && p_dirent->d_name[0] <= '9') //判断是否是进程文件
            {
                sprintf(temp_file_path, "/proc/%s/status", p_dirent->d_name);
                fp = fopen(temp_file_path, "r");
                if (fp)
                {
                    fgets(con, BUFFERSIZE, fp);
                    fclose(fp);
                    sscanf(con, "%*s%s", temp_name);
                    if (strcmp(temp_name, proc_data.name) == 0)
                    {
                        // printf("%s\n", temp_name);
                        int row, t_pid, pid = atoi(p_dirent->d_name);
                        gchar *pid_text = NULL;
                        if (kill(pid, SIGKILL) == -1) //判断是否可以杀死进程
                        {
                            GtkWidget *dialog;
                            dialog = gtk_message_dialog_new(GTK_WINDOW(window),
                                                            GTK_DIALOG_DESTROY_WITH_PARENT,
                                                            GTK_MESSAGE_ERROR,
                                                            GTK_BUTTONS_OK,
                                                            "权限不够，无法结束该进程！");
                            gtk_window_set_title(GTK_WINDOW(dialog), "错误");
                            gtk_widget_show(dialog);
                            gtk_dialog_run(GTK_DIALOG(dialog));
                            gtk_widget_destroy(dialog);
                            perror("No authority");
                            break;
                        }
                        else //进程被杀死
                        {
                            GtkWidget *dialog;
                            dialog = gtk_message_dialog_new(GTK_WINDOW(window),
                                                            GTK_DIALOG_DESTROY_WITH_PARENT,
                                                            GTK_MESSAGE_INFO,
                                                            GTK_BUTTONS_OK,
                                                            "进程：%s 已被杀死！", temp_name);
                            gtk_window_set_title(GTK_WINDOW(dialog), "提示");
                            gtk_widget_show(dialog);
                            gtk_dialog_run(GTK_DIALOG(dialog));
                            gtk_widget_destroy(dialog);
                            printf("Kill process correctly!\n");
                            return TRUE;
                        }

                        // for (row = 0; row < GTK_CLIST(clist)->rows; row++)
                        // {
                        //     gtk_clist_get_text(GTK_CLIST(clist), row, 1, &pid_text);
                        //     sscanf(pid_text, "%d", &t_pid);
                        //     if (t_pid == pid)
                        //     {
                        //         gtk_clist_remove(GTK_CLIST(clist), row);
                        //         proc_data.n_flag = FALSE;
                        //         closedir(pdir);
                        //         printf("Remove process!\n");
                        //         // gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); //杀死进程，按钮不使能
                        //         return TRUE;
                        //     }
                        // }
                    }
                }
            }
        }
        if (p_dirent == NULL) //进程不存在
        {
            GtkWidget *dialog;
            dialog = gtk_message_dialog_new(GTK_WINDOW(window),
                                            GTK_DIALOG_DESTROY_WITH_PARENT,
                                            GTK_MESSAGE_ERROR,
                                            GTK_BUTTONS_OK,
                                            "进程不存在，无法结束该进程！");
            gtk_window_set_title(GTK_WINDOW(dialog), "错误");
            gtk_widget_show(dialog);
            gtk_dialog_run(GTK_DIALOG(dialog));
            gtk_widget_destroy(dialog);
            perror("No such process");
        }
        // proc_data.flag = FALSE;
        closedir(pdir);
    }
    else //通过进程PID杀死一个进程
    {
        if (proc_data.name[0] < '0' || proc_data.name[0] > '9') //判断输入是否为数字PID
        {
            GtkWidget *dialog;
            dialog = gtk_message_dialog_new(GTK_WINDOW(window),
                                            GTK_DIALOG_DESTROY_WITH_PARENT,
                                            GTK_MESSAGE_ERROR,
                                            GTK_BUTTONS_OK,
                                            "请输入正确的进程PID！");
            gtk_window_set_title(GTK_WINDOW(dialog), "错误");
            gtk_widget_show(dialog);
            gtk_dialog_run(GTK_DIALOG(dialog));
            gtk_widget_destroy(dialog);
            perror("PID error");
        }
        else //输入为数字
        {
            int pid = atoi(proc_data.name);
            char temp_proc_path[64];
            sprintf(temp_proc_path, "/proc/%d", pid);
            if (fopen(temp_proc_path, "r") == NULL) //判断进程是否存在
            {
                GtkWidget *dialog;
                dialog = gtk_message_dialog_new(GTK_WINDOW(window),
                                                GTK_DIALOG_DESTROY_WITH_PARENT,
                                                GTK_MESSAGE_ERROR,
                                                GTK_BUTTONS_OK,
                                                "进程不存在，无法结束该进程！");
                gtk_window_set_title(GTK_WINDOW(dialog), "错误");
                gtk_widget_show(dialog);
                gtk_dialog_run(GTK_DIALOG(dialog));
                gtk_widget_destroy(dialog);
                perror("No such process");
            }
            else //进程存在，进一步判断是否可以杀死
            {
                if (kill(pid, SIGKILL) == -1) //权限不够，无法杀死进程
                {
                    GtkWidget *dialog;
                    dialog = gtk_message_dialog_new(GTK_WINDOW(window),
                                                    GTK_DIALOG_DESTROY_WITH_PARENT,
                                                    GTK_MESSAGE_ERROR,
                                                    GTK_BUTTONS_OK,
                                                    "权限不够，无法结束该进程！");
                    gtk_window_set_title(GTK_WINDOW(dialog), "错误");
                    gtk_widget_show(dialog);
                    gtk_dialog_run(GTK_DIALOG(dialog));
                    gtk_widget_destroy(dialog);
                    perror("No authority");
                }
                else //杀死进程
                {
                    GtkWidget *dialog;
                    dialog = gtk_message_dialog_new(GTK_WINDOW(window),
                                                    GTK_DIALOG_DESTROY_WITH_PARENT,
                                                    GTK_MESSAGE_ERROR,
                                                    GTK_BUTTONS_OK,
                                                    "PID=%d 的进程已被杀死！", pid);
                    gtk_window_set_title(GTK_WINDOW(dialog), "提示");
                    gtk_widget_show(dialog);
                    gtk_dialog_run(GTK_DIALOG(dialog));
                    gtk_widget_destroy(dialog);
                    printf("Kill process correctly!\n");
                    return TRUE;
                    // gchar *pid_text = NULL;
                    // int t_pid = 0;
                    // for (int row = 0; row < GTK_CLIST(clist)->rows; row++)
                    // {
                    //     gtk_clist_get_text(GTK_CLIST(clist), row, 1, &pid_text);
                    //     sscanf(pid_text, "%d", &t_pid);
                    //     if (t_pid == pid)
                    //     {
                    //         gtk_clist_remove(GTK_CLIST(clist), row);
                    //         proc_data.flag = FALSE;
                    //         // gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); //杀死进程，按钮不使能
                    //         return TRUE;
                    //     }
                    // }
                }
            }
        }
    }
    // }
    // gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); //杀死进程，按钮不使能
    return TRUE;
}

gint refrush_process(gpointer clist)
{
    // pthread_t re_proc;
    // pthread_create(&re_proc, NULL, get_process_info, NULL);
    // pthread_join(re_proc, NULL);
    get_process_info(clist);
    refrush_process_num();
    // pthread_create(&re_proc, NULL, refrush_process_num, NULL);
    // pthread_join(re_proc, NULL);
    return TRUE;
}

gint shutdown_now() //关机
{
    gtk_main_quit();
    system("shutdown -r now");
}

gint main_quit(gpointer data)
{
    for (int i = 0; i < 4; i++)
    {
        gtk_timeout_remove(timeout_tag[i]);
    }
    gtk_main_quit();
}

int main(int argc, char *argv[])
{
    GtkWidget *note;
    GtkWidget *vbox;
    GtkWidget *hbox;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(main_quit), NULL);
    gtk_container_set_border_width(GTK_CONTAINER(window), 10); //设置窗口边框长度
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    // gtk_window_set_default_size(GTK_WINDOW(window), 560, 500);
    gtk_window_set_resizable(GTK_WINDOW(window), TRUE); //设置窗口可以伸缩
    gtk_window_set_title(GTK_WINDOW(window), "系统监视器");

    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(window), vbox);
    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);

    //初始化cpu和内存使用y坐标
    for (int i = 0; i < 121; i++)
    {
        y_co.my[i] = y_co.cy[i] = y_co.sy[i] = 200;
    }
    y_co.i = 0;
    char temp_buf[BUFFERSIZE];
    //获取CPU使用率
    get_cpu_rate(temp_buf);
    cpu_label = gtk_label_new(temp_buf);
    gtk_box_pack_start(GTK_BOX(hbox), cpu_label, TRUE, TRUE, 0);
    timeout_tag[3] = gtk_timeout_add(1000, refrush_time_CPU_mem, NULL);

    //获取MEM使用率
    get_mem_rate(temp_buf);
    mem_label = gtk_label_new(temp_buf);
    gtk_box_pack_start(GTK_BOX(hbox), mem_label, TRUE, TRUE, 0);

    //获得当前时间
    get_start_time(0, temp_buf);
    time_label = gtk_label_new(temp_buf);
    gtk_box_pack_start(GTK_BOX(hbox), time_label, TRUE, TRUE, 0);

    //关机按键
    GtkWidget *exit = (GtkWidget *)gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
    gtk_box_pack_start(GTK_BOX(hbox), exit, FALSE, FALSE, 0);
    g_signal_connect(G_OBJECT(exit), "clicked", G_CALLBACK(shutdown_now), NULL);

    note = gtk_notebook_new(); //新建notebook
    gtk_box_pack_start(GTK_BOX(vbox), note, TRUE, TRUE, 0);
    init_page1(note);
    init_page2(note);
    init_page3(note);
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}